package com.hjp.mylock.lock;

import com.hjp.mylock.util.UnsafeInstance;
import sun.misc.Unsafe;

import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.locks.LockSupport;

public class AqsLock {

    //加锁次数标记
    private volatile int state = 0;
    //持有锁的线程
    private Thread lockHolder;
    //基于cas保证线程安全的队列
    private ConcurrentLinkedQueue<Thread> waiters = new ConcurrentLinkedQueue<>();

    public int getState() {
        return state;
    }

    public void setState(int state) {
        this.state = state;
    }

    public Thread getLockHolder() {
        return lockHolder;
    }

    public void setLockHolder(Thread lockHolder) {
        this.lockHolder = lockHolder;
    }

    public boolean aquire() {
        //cas比较与交换-原子算法
        Thread thread = Thread.currentThread();
        int state = getState();
        if (state == 0) {//同步器还没有被持有
            if (waiters.size() == 0//代表队列里没有线程，就是说这个线程是第一个执行此方法的线程
                    ||waiters.peek()==thread//代表当前线程是刚从队列里移除的队头线程，也应该加锁成功
                    && compareAndSwapState(0, 1)//通过cas保证原子操作，如果是预期值则更新
            ) {
                setLockHolder(thread);
                return true;
            }
        }
        return false;
    }
    /**
     * 加锁
     */
    public void lock() {
        if (aquire()) {
            //如果加锁成功
            return;
        }
        //还没加锁成功的线程
        Thread thread = Thread.currentThread();
        //把当前线程放入队列等待
        waiters.add(thread);
        for (; ; ) {//开启自旋，把没有获取锁的线程放入队列并阻塞
            //判断当前线程是不是队列头部，如果是再去获得锁
            if (thread==waiters.peek()&&aquire()) {
                //从队列中移除拿到锁的线程
                waiters.poll();
                return;
            }
            //阻塞当前线程
            LockSupport.park(thread);
        }
    }

    /**
     * 解锁
     */
    public void unlock() {
        if (Thread.currentThread()!=lockHolder){//如果当前来解锁的线程不是获得锁的线程，抛出异常
            //throw new RuntimeException("lockholder is not current thread");
            return;
        }
        int state = getState();
        if (compareAndSwapState(state,0)){//置换回初始状态0
            //移除当前获得锁的线程
            setLockHolder(null);
            //从队列头部拿出线程，唤醒
            Thread headThread = waiters.peek();
            if (headThread!=null){
                //唤醒队列头部的线程，它会继续去lock方法走循环
                LockSupport.unpark(headThread);
            }
        }

    }

    //获取Unsafe
    private static final Unsafe unsafe = UnsafeInstance.reflectGetUnsafe();
    //偏移量
    private static  long stateoffset;

    /*
     * 原子操作
     * */
    public final boolean compareAndSwapState(int expect, int update) {
        return unsafe.compareAndSwapInt(this, stateoffset, expect, update);
    }

    static {
        try {
            stateoffset = unsafe.objectFieldOffset(AqsLock.class.getDeclaredField("state"));
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }

}
